package com.fjwt.gz.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.DesensitizedUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONUtil;
import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.fjwt.gz.components.oss.model.MockMultipartFile;
import com.fjwt.gz.components.oss.model.OssFileConfig;
import com.fjwt.gz.components.oss.service.OssFileService;
import com.fjwt.gz.core.constants.Constants;
import com.fjwt.gz.core.exception.BizException;
import com.fjwt.gz.core.model.security.GzUserDetails;
import com.fjwt.gz.db.dto.AwardVirtualCdkDTO;
import com.fjwt.gz.db.entity.AwardVirtualCdkEntity;
import com.fjwt.gz.db.entity.OssRecordEntity;
import com.fjwt.gz.db.vo.AwardVirtualCdkVO;
import com.fjwt.gz.service.mapper.AwardVirtualCdkMapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.FileInputStream;
import java.util.*;

/**
 * <p>
 * 虚拟奖品CDK表 服务实现类
 * </p>
 *
 * @author shiyonghao
 * @since 2025-04-09
 */
@Slf4j
@Service
public class AwardVirtualCdkService extends ServiceImpl<AwardVirtualCdkMapper, AwardVirtualCdkEntity> {

    @Autowired
    private OssRecordService ossRecordService;

    @Autowired
    private OssFileService ossFileService;

    @Autowired
    private AgentInfoService agentInfoService;

    /**
     * 查询列表
     *
     * @param iPage
     * @param awardCdkDTO
     * @return
     */
    public IPage<AwardVirtualCdkVO> queryList(IPage iPage, AwardVirtualCdkDTO awardCdkDTO) {
        if (StrUtil.isNotBlank(awardCdkDTO.getAgentNo())) {
            awardCdkDTO.setAgentNoList(agentInfoService.queryAllSubAgentNo(awardCdkDTO.getAgentNo()));
            awardCdkDTO.setAgentNo(null);
        }
        IPage<AwardVirtualCdkVO> awardCdkVOIPage = baseMapper.selectListByParams(iPage, awardCdkDTO);
        if (!CollectionUtils.isEmpty(awardCdkVOIPage.getRecords())) {
            awardCdkVOIPage.getRecords().forEach(
                    entity -> {
                        entity.setCdk(DesensitizedUtil.mobilePhone(entity.getCdk()));
                    }
            );
        }
        return awardCdkVOIPage;
    }

    /**
     * 导入cdk
     * @param awardCdkDTO
     * @param bizType
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public String importCdk(AwardVirtualCdkDTO awardCdkDTO, String bizType) {
        // 校验参数
        if (ObjectUtils.isEmpty(awardCdkDTO.getVirtualInsideId()) || ObjectUtils.isEmpty(awardCdkDTO.getOssFileUrl())) {
            throw new BizException("请求参数异常，请检查！");
        }

        // 获取导入数据
        List<AwardVirtualCdkVO> awardVirtualCdkVOList = getCdkList(awardCdkDTO.getOssFileUrl(), bizType);
        log.info("新增CDK导入文件数据：{}", JSONUtil.toJsonStr(awardVirtualCdkVOList));

        if (CollUtil.isEmpty(awardVirtualCdkVOList)) {
            throw new BizException("导入文档为空！");
        }

        // 查询oss上传记录
        LambdaQueryWrapper<OssRecordEntity> ossRecordWrapper = new LambdaQueryWrapper<>();
        ossRecordWrapper.eq(OssRecordEntity::getOssUrl,awardCdkDTO.getOssFileUrl());
        ossRecordWrapper.eq(OssRecordEntity::getUploadType, Constants.OSS_UPLOAD_TYPE.VIRTUAL_CDK_IMPORT);
        OssRecordEntity recordEntity = ossRecordService.getBaseMapper().selectOne(ossRecordWrapper);
        if(Objects.isNull(recordEntity)){
            throw new BizException("导入失败！未找到，导入文件");
        }

        Long virtualInsideId = awardCdkDTO.getVirtualInsideId();
        Long createdUid = awardCdkDTO.getCreatedUid();

        List<AwardVirtualCdkVO> filterCdkList = awardVirtualCdkVOList.stream()
                .filter(f -> StringUtils.isNotBlank(f.getCdk())).toList();

        if (CollUtil.isEmpty(filterCdkList)) {
            throw new BizException("导入文档为空！");
        }
        List<AwardVirtualCdkVO> errorCdkList = new ArrayList<>();
        List<AwardVirtualCdkEntity> awareCdkList = new ArrayList<>();
        for (AwardVirtualCdkVO virtualCdkVO : filterCdkList) {
            //查询该cdk是否已导入
            AwardVirtualCdkEntity virtualCdkEntity = this.getOne(AwardVirtualCdkEntity.gw().eq(AwardVirtualCdkEntity::getCdk, virtualCdkVO.getCdk())
                    .eq(AwardVirtualCdkEntity::getVirtualInsideId, virtualInsideId));
            if (virtualCdkEntity != null) {
                virtualCdkVO.setRemark("此CDK已存在");
                errorCdkList.add(virtualCdkVO);
                continue;
            }
            AwardVirtualCdkEntity awardCdkEntity = new AwardVirtualCdkEntity();
            awardCdkEntity.setVirtualInsideId(virtualInsideId)
                    .setCdk(virtualCdkVO.getCdk())
                    .setIsConsume(0)
                    .setCreatedUid(createdUid);
            awareCdkList.add(awardCdkEntity);
        }
        saveBatch(awareCdkList);
        return failOssUrl(errorCdkList);
    }

    /**
     * oss文件导入渠道
     * @return
     */
    public List<AwardVirtualCdkVO> getCdkList(String ossFileUrl, String bizType) {
        File file = null;
        try {
            file = FileUtil.file(String.format("./temp/%s.xlsx", DateUtil.date().getTime()));
            HttpUtil.downloadFile(ossFileUrl, file);

            LambdaQueryWrapper<OssRecordEntity> ossRecordWrapper = OssRecordEntity.gw();
            ossRecordWrapper.eq(OssRecordEntity::getOssUrl, ossFileUrl);
            ossRecordWrapper.eq(OssRecordEntity::getUploadType, Constants.OSS_UPLOAD_TYPE.ACTIVITY_CHANNEL_IMPORT);
            OssRecordEntity recordEntity = ossRecordService.getBaseMapper().selectOne(ossRecordWrapper);

            if (recordEntity == null) {
                OssRecordEntity ossRecordEntity = new OssRecordEntity();
                ossRecordEntity.setBizType(bizType);
                ossRecordEntity.setOssUrl(ossFileUrl);
                ossRecordEntity.setFileSize(file.length());
                ossRecordEntity.setUploadType(Constants.OSS_UPLOAD_TYPE.VIRTUAL_CDK_IMPORT);
                ossRecordEntity.setSysUserId(GzUserDetails.getCurrentUserDetails().getSysUser().getSysUserId());
                ossRecordEntity.setCreatedAt(new Date());
                ossRecordService.save(ossRecordEntity);
            } else {
                OssRecordEntity ossRecordEntity = new OssRecordEntity();
                ossRecordEntity.setOssRecordId(recordEntity.getOssRecordId());
                ossRecordEntity.setOssUrl(ossFileUrl);
                ossRecordService.getBaseMapper().updateById(ossRecordEntity);
            }

            try (ExcelReader reader = ExcelUtil.getReader(file)) {
                reader.addHeaderAlias("CDK", "cdk");

                return reader.readAll(AwardVirtualCdkVO.class);
            }
        } catch (Exception e) {
            log.error("文件下载或读取失败: {}", e.getMessage(), e);
            throw new BizException("文件下载或读取失败");
        } finally {
            if (file != null) {
                FileUtil.del(file);
            }
        }
    }

    public String failOssUrl(List<AwardVirtualCdkVO> errorCdkList) {
        String failUrl = "";
        if (CollUtil.isEmpty(errorCdkList)) {
            return failUrl;
        }
        String successFileName = String.format("./temp/compareMchInfo/fail/%s.xlsx", DateUtil.date().getTime());
        File normalFile = new File(successFileName);
        ExcelWriter failWriter = ExcelUtil.getWriter(normalFile);
        failWriter.addHeaderAlias("cdk", "CDK");
        failWriter.addHeaderAlias("remark", "导入失败原因");
        try {
            failWriter.write(errorCdkList);
            failWriter.close();
            MultipartFile multipartFile = new MockMultipartFile(successFileName, normalFile.length(), new FileInputStream(normalFile));
            failUrl = ossFileService.singleFileUpload(multipartFile, OssFileConfig.BIZ_TYPE.DOWNLOAD);
            // 添加oos上传记录
            OssRecordEntity ossRecordEntity = new OssRecordEntity();
            ossRecordEntity.setBizType(OssFileConfig.BIZ_TYPE.DOWNLOAD);
            ossRecordEntity.setOssUrl(failUrl);
            ossRecordEntity.setFileSize(normalFile.length());
            ossRecordEntity.setUploadType(Constants.OSS_UPLOAD_TYPE.MCH_INFO_COMPARE_FAIL);
            ossRecordEntity.setCreatedAt(new Date());
            ossRecordService.save(ossRecordEntity);
        } catch (Exception e) {
            throw new BizException(e.getMessage());
        }
        return failUrl;
    }

    /**
     * 查询已划拨的CDK列表
     * @param iPage
     * @param awardCdkDTO
     * @return
     */
    public IPage<AwardVirtualCdkVO> queryUsedCdkList(IPage iPage, AwardVirtualCdkDTO awardCdkDTO) {
        if (StrUtil.isNotBlank(awardCdkDTO.getAgentNo())) {
            awardCdkDTO.setAgentNoList(agentInfoService.queryAllSubAgentNo(awardCdkDTO.getAgentNo()));
            awardCdkDTO.setAgentNo(null);
        }
        return baseMapper.queryUsedCdkList(iPage, awardCdkDTO);
    }
}
